package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.provider.dto.DeploymentDto;
import com.csun.cmny.provider.exceptions.OmcBizException;
import com.csun.cmny.provider.service.OmcActivitiService;
import com.csun.cmny.util.PublicUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.*;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2019-05-29 09:53
 * @Description: the class omc activiti service impl
 */
@Slf4j
@Data
@Service
@Transactional
public class OmcActivitiServiceImpl implements OmcActivitiService {

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private TaskService taskService;

    @Resource
    private ProcessEngine processEngine;

    @Resource
    private RepositoryService repositoryService;

    @Resource
    private HistoryService historyService;


    /**
     * 创建流程部署
     *
     * @param deploymentDto deployment dto
     * @param loginAuthDto  login auth dto
     * @return the deployment
     */
    @Override
    public Deployment createDeployment(DeploymentDto deploymentDto, LoginAuthDto loginAuthDto) {

        // 校验流程是否已经部署
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(deploymentDto.getProcessKey())        // 流程key
                .processDefinitionTenantId("" + loginAuthDto.getGroupId())  // 流程租户
                .singleResult();

        if (PublicUtil.isNotEmpty(processDefinition)) {
            throw new OmcBizException(ErrorCodeEnum.OMC10032001);
        }

        return repositoryService.createDeployment()
                .name(deploymentDto.getDeploymentName())	// 流程部署名称
                .tenantId("" + loginAuthDto.getGroupId())   // 流程租户
                .addClasspathResource(deploymentDto.getDeploymentResource())    // 资源路径
                .deploy();
    }

    /**
     * 删除流程部署
     *
     * @param processKey   process key
     * @param groupId   the group id
     */
    @Override
    public void deleteDeployment(String processKey, Long groupId) {

        // 校验流程key
        if (PublicUtil.isEmpty(processKey)) {
            throw new OmcBizException(ErrorCodeEnum.OMC10032002);
        }

        // 校验流程是否已经部署
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(processKey)       // 流程key
                .processDefinitionTenantId("" + groupId)  // 流程租户
                .singleResult();

        if (PublicUtil.isEmpty(processDefinition)) {
            throw new OmcBizException(ErrorCodeEnum.OMC10032003);
        }
        log.info("processDefinition = {}", processDefinition);

        // 删除流程部署
        repositoryService.deleteDeployment(processDefinition.getDeploymentId(),true);
    }

    /**
     * 启动流程实例
     *
     * @param processKey 流程key
     * @param variables  要传递的变量
     * @param groupId    组织Id
     * @return 流程实例
     */
    @Override
    public ProcessInstance startProcessInstanceByKeyAndTenantId(String processKey, Map<String, Object> variables, Long groupId) {

        // 校验流程是否已经部署
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(processKey)       // 流程key
                .processDefinitionTenantId("" + groupId)  // 流程租户
                .singleResult();
        if (PublicUtil.isEmpty(processDefinition)) {
            throw new OmcBizException(ErrorCodeEnum.OMC10032003);
        }

        // 启动
        return runtimeService.startProcessInstanceByKeyAndTenantId(processKey,
                variables, groupId.toString());
    }

    /**
     * 根据流程实例Id获取当前流程任务
     *
     * @param processInstanceId 流程实例Id
     * @return 任务
     */
    @Override
    public Task getTaskByProcessInstanceId(String processInstanceId) {

        return taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
    }

    /**
     * 完成任务
     *
     * @param task 待完成的任务
     */
    @Override
    public void completeTask(Task task) {
    }

    /**
     * 添加任务批注
     *
     * @param task                待添加批注的任务
     * @param authenticatedUserId 执行人
     * @param message             批注
     */
    @Override
    public void addTaskComment(Task task, String authenticatedUserId, String message) {

        Authentication.setAuthenticatedUserId(authenticatedUserId);

        taskService.addComment(task.getId(), task.getProcessInstanceId(), message);
    }

    /**
     * 关闭流程实例
     *
     * @param processInstanceId 流程实例Id
     * @param deleteReason      流程实例理由
     */
    @Override
    public void deleteProcessInstance(String processInstanceId, String deleteReason) {

        // 判断流程实例是否已经完成
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();

        if (PublicUtil.isEmpty(processInstance)) {
            // 流程实例已经完成
            throw new OmcBizException(ErrorCodeEnum.OMC10032007);
        }

        runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
    }
}
